/** This class represents a connected member 
 *  @author ChrM */

package com.jtalker.server;

import java.util.ArrayList;

public class JTalkerMember {
	// Static Vars
	public static final String USER_TYPE_WEBCLIENT = "webclient";
	public static final String USER_TYPE_PERSISTENT = "persistent";
	public static final String USER_TYPE_CHATROOM = "chatroom";
	// Invalidate after one minute
	// TODO: make session duration variable!
	public static final int SESSION_DURATION = 60000;

	/** Corresponding network thread */
	private JTalkerServerThread myThread = null;

	/** Constructor */
	public JTalkerMember(String userName, String userIP, String userPort,
			String userStatus, String userType) {
		this.userName = userName;
		this.userIP = userIP;
		this.userPort = userPort;
		this.userStatus = userStatus;
		// TODO: special functions for a chatroom "user"
		if (this.userIP == null){
			this.userIP = "server";
		}
		if (this.userPort == null){
			this.userPort = "-1";
		}
		if (this.userStatus == null){
			this.userStatus = "normal";
		}
		if (userType == null 
				|| (!userType.equals(USER_TYPE_WEBCLIENT) && !userType.equals(USER_TYPE_PERSISTENT) 
						&& !userType.equals(USER_TYPE_CHATROOM))){
			this.userType = USER_TYPE_PERSISTENT; // Default
		}else{
			this.userType = userType;
		}
		this.userSID = this.generateSessionID();
		this.userSidGeneratingDate = System.currentTimeMillis();

		this.isOnline = true;
	}

	/** Sets the corresponding thread */
	public void setThread(JTalkerServerThread thread) {
		this.myThread = thread;
	}

	/** Gets a user info */
	public String getUserInfo() {
		return (this.userName + " AT " + this.userIP);
	}

	/** Gets a user name */
	public String getUserName() {
		return this.userName;
	}

	/** Sets users role */
	public boolean setUserRole(String role) {
		if (role.equals(JTalkerParser.GlobalUser.USER)
				|| role.equals(JTalkerParser.GlobalUser.ADMIN)
				|| role.equals(JTalkerParser.GlobalUser.ROOT)) {
			this.userRole = role;
			return true;
		} else {
			return false;
		}
	}

	/** Gets users role */
	public String getUserRole() {
		return this.userRole;
	}

	/** Gets users role as int value */
	public int getUserRoleValue() {
		if (this.userRole.equals(JTalkerParser.GlobalUser.USER)){
			return 0;
		}else if (this.userRole.equals(JTalkerParser.GlobalUser.ADMIN)){
			return 1;
		}else if (this.userRole.equals(JTalkerParser.GlobalUser.ROOT)){
			return 2;
		}else{
			return -1;
		}
	}

	/** Gets the Port-Number as int */
	public int getPort() {
		return Integer.parseInt(this.userPort);
	}

	/** Sets a new IP and Port number. For web-clients only! */
	public boolean updateConnectionData(String newIP, String newPort) {
		if (this.userType.equals(USER_TYPE_WEBCLIENT)) {
			this.userIP = newIP;
			this.userPort = newPort;
			return true;
		}

		return false;
	}

	/** Gets user status */
	public String getUserStatus() {
		return this.userStatus;
	}

	/** Gets user IP adress */
	public String getUserIP() {
		return this.userIP;
	}

	/** Gets the Session ID */
	public String getSessionID() {
		return this.userSID;
	}

	/** Gets user type */
	public String getUserType() {
		return this.userType;
	}

	/** Checks if this is a chat-room */
	public boolean isChatroom() {
		return this.userType.equals(JTalkerMember.USER_TYPE_CHATROOM);
	}

	/** Sets user status */
	public void setUserStatus(String status) {
		if (!this.userStatus.equalsIgnoreCase(status)) {
			this.userStatus = status;
			this.sendUpdateRequestToAll();
		}
	}

	/** Adds a set of messages to the queue */
	public synchronized boolean addMessages(Message[] messages) {
		if (this.lockQueue){
			return false;
		}
		for (int i = 0; i < messages.length; i++) {
			this.messageQueue.add(new Message(messages[i].content,
					messages[i].sender, messages[i].type,
					messages[i].subject, messages[i].ID));
		}
		this.sendUpdateRequest();
		return true;
	}

	/** Adds a new message to the queue */
	public synchronized boolean addMessage(String content, String sender,
			String type, String subject, String id) {
		if (this.lockQueue){
			return false;
		}
		// Extensions for chat room
		if (this.userType.equals(JTalkerMember.USER_TYPE_CHATROOM)) {
			if (!type.equals("file")){
				content = "&lt;b&gt;" + sender + ":&lt;/b&gt; " + content;
			}
			sender = this.userName;
		}
		this.messageQueue.add(new Message(content, sender, type, subject, id));
		this.sendUpdateRequest();
		return true;
	}

	/** Gets the number of queued messages */
	public int numOfMsgs() {
		return this.messageQueue.size();
	}

	/** Gets all messages and delete they after this */
	public synchronized Message[] getMessages() {
		this.lockQueue = true;
		Message[] tmpArray = new Message[this.messageQueue.size()];
		this.messageQueue.toArray(tmpArray);
		this.messageQueue.clear();
		this.lockQueue = false;
		return tmpArray;
	}

	/** Gets the oldest message and delete this one! */
	public synchronized Message getMessage() {
		if (!this.messageQueue.isEmpty()) {
			this.lockQueue = true;
			Message msg = this.messageQueue.get(0);
			this.messageQueue.remove(0);
			this.lockQueue = false;
			return msg;
		} else
			return null;
	}

	/** Checks if this Session ID is still valid */
	public boolean isSessionValid() {
		// Only for webclient
		if (!this.userType.equals(USER_TYPE_WEBCLIENT))
			return true;

		if (this.sessionClosed
				|| (System.currentTimeMillis() - this.userSidGeneratingDate) > JTalkerMember.SESSION_DURATION /*
																											 * &&
																											 * !
																											 * this
																											 * .
																											 * isOnline
																											 */)
			return false;
		else
			return true;
	}

	/** Updates the session ID on access */
	public void updateSessionID() {
		if (!this.sessionClosed)
			this.userSidGeneratingDate = System.currentTimeMillis();
	}

	/** Makes this session invalid */
	public boolean closeSession() {
		if (this.userType.equals(USER_TYPE_PERSISTENT)){
			return false;
		}
		this.sessionClosed = true;
		return true;
	}

	/** Generates a unique session ID */
	private String generateSessionID() {
		String in = this.userPort + System.currentTimeMillis();

		// Use a global hash-method
		return JTalkerServer.makeHash(in);
	}

	/**
	 * Set chat-room Users
	 * 
	 * @param users
	 *            A list of allowed users for this chat-room (separated by ",")
	 * @return true, if the user list was created successfully
	 */
	public boolean setChatroomUsers(String users) {
		if (!this.isChatroom()){
			return false;
		}
		if (users == null || users.length() < 1){
			return false;
		}
		if (this.chatroomUsers == null){
			this.chatroomUsers = new ArrayList<String>();
		} else {
			this.chatroomUsers.clear();
		}
		String[] tmpUsers = users.split(",");
		String tmpUserName = "";
		for (int i = 0; i < tmpUsers.length; i++) {
			tmpUserName = tmpUsers[i].trim();
			if (JTalkerServer.isAllowedUserName(tmpUserName)){
				this.chatroomUsers.add(tmpUserName);
			}
		}

		this.makeChatroomUsersListUnique();
		return true;
	}

	/**
	 * Checks if the user list is unique (no multiple user items in the list).
	 * If not, the list will be corrected
	 */
	private synchronized boolean makeChatroomUsersListUnique() {
		if (!this.isChatroom()){
			return false;
		}
		String tmpName = null;
		int numOfHits = 0;
		boolean retVal = true;
		for (int i = 0; i < this.chatroomUsers.size(); i++) {
			tmpName = this.chatroomUsers.get(i);
			numOfHits = 0;
			for (int j = 0; j < this.chatroomUsers.size(); j++) {
				if (tmpName.equals(this.chatroomUsers.get(j))) {
					numOfHits++;
					if (numOfHits > 1) {
						this.chatroomUsers.remove(j);
						numOfHits--;
						j--;
						retVal = false;
					}
				}
			}
		}
		return retVal;
	}

	/** Add chat-room user */
	public synchronized boolean addChatroomUser(String user) {
		if (!this.isChatroom()){
			return false;
		}
		if (user == null || user.length() < 1
				|| !JTalkerServer.isAllowedUserName(user)){
			return false;
		}
		if (this.chatroomUsers == null){
			this.chatroomUsers = new ArrayList<String>();
		}
		if (!this.isChatroomUser(user)) {
			this.chatroomUsers.add(user);
		} else {
			return false;
		}
		return true;
	}

	/** Removes chatroom user */
	public synchronized boolean removeChatroomUser(String userName) {
		if (!this.isChatroom()){
			return false;
		}
		if (userName == null || userName.length() < 1){
			return false;
		}
		if (this.isChatroomUser(userName)) {
			for (int i = 0; i < this.chatroomUsers.size(); i++) {
				if (userName.equals(this.chatroomUsers.get(i))) {
					this.chatroomUsers.remove(i);
					return true;
				}
			}
		}

		return false;
	}

	/** Sets the chat-room administrator */
	public boolean setChatroomAdmin(String admin) {
		if (!this.isChatroom()){
			return false;
		}
		if (admin == null || admin.length() < 1){
			return false;
		}
		this.chatroomAdmin = admin;

		return this.addChatroomUser(admin);
	}

	/** Gets chat-rooms administrator */
	public String getChatroomAdmin() {
		if (!this.isChatroom()){
			return "";
		}
		return this.chatroomAdmin;
	}

	/** Gets all allowed users for this chatroom */
	public String[] getChatroomUsers() {
		if (!this.isChatroom()){
			return new String[0];
		}
		if (this.chatroomUsers == null){
			return new String[0];
		}
		String tmpUsers[] = new String[this.chatroomUsers.size()];
		this.chatroomUsers.toArray(tmpUsers);
		return tmpUsers;
	}

	/** Checks if a user is member of the chat-room */
	public boolean isChatroomUser(String user) {
		if (!this.isChatroom()){
			return false;
		}
		String[] tmpList = this.getChatroomUsers();

		for (int i = 0; i < tmpList.length; i++) {
			if (user.equals(tmpList[i])){
				return true;
			}
		}

		return false;
	}

	/** Sends the update message to this member */
	public boolean sendUpdateRequest() {
		if (this.myThread != null) {
			this.myThread.sendUpdateRequest();
			return true;
		} else {
			return false;
		}
	}

	/** Sends the update message to all members */
	public boolean sendUpdateRequestToAll() {
		if (this.myThread != null) {
			this.myThread.parent.sendUpdateRequestToAll(this.userName);
			return true;
		} else {
			return false;
		}
	}

	// private members
	private String userName = "unnamed";
	private String userIP = "127.0.0.1";
	private String userPort = "1975";
	private String userStatus = null; // or "normal" or "busy"
	private String userType = JTalkerMember.USER_TYPE_PERSISTENT;
	private String userSID = null;

	// TODO: use roles and contact lists
	private String userRole = JTalkerParser.GlobalUser.USER;
	private String userContactList = JTalkerParser.GlobalUser.CONTACTS_ALL;

	private long userSidGeneratingDate = -1;
	private ArrayList<Message> messageQueue = new ArrayList<Message>();
	private boolean lockQueue = false;
	public boolean isOnline = false;
	public boolean sessionClosed = false;
	// Specials for chat-room
	private ArrayList<String> chatroomUsers = null; // Allowed users for this chatroom
	/** Creator of this Chat-room */
	private String chatroomAdmin = null;

	/** This inner class represents a message */
	public class Message {
		public Message(String content, String sender, String type,
				String subject, String ID) {
			// TODO: add send time!
			// this.sendtime = _sendtime;
			this.content = content;
			this.sender = sender;
			this.type = type;
			if (type == null){
				this.type = "normal";
			}
			this.subject = subject;
			this.ID = ID;
		}

		public String content = null;
		public String sender = null;
		public String type = null;
		public String subject = null;
		public String ID = null;
	}
}
